import { useState, useCallback, useEffect, useRef } from 'react'
import type { 
  BarrageSettings, 
  SettingChangeEvent,
  SettingsPanelState
} from '../types/settings'
import { 
  DEFAULT_BARRAGE_SETTINGS
} from '../types/settings'

// 本地存储键名
const STORAGE_KEY = 'barrage-settings'

// 设置面板默认状态
const DEFAULT_PANEL_STATE: SettingsPanelState = {
  isOpen: false,
  position: { x: 0, y: 0 },
  animating: false
}

/**
 * 弹幕设置管理Hook
 * 提供设置的状态管理、持久化、验证等功能
 */
export const useBarrageSettings = () => {
  // 当前设置状态
  const [settings, setSettings] = useState<BarrageSettings>(DEFAULT_BARRAGE_SETTINGS)
  
  // 设置面板状态
  const [panelState, setPanelState] = useState<SettingsPanelState>(DEFAULT_PANEL_STATE)
  
  // 设置变更监听器
  const [changeListeners, setChangeListeners] = useState<Array<(event: SettingChangeEvent) => void>>([])
  
  // 设置按钮引用（用于定位弹出框）
  const settingsButtonRef = useRef<HTMLButtonElement>(null)
  
  // 弹出框引用
  const panelRef = useRef<HTMLDivElement>(null)

  /**
   * 从本地存储加载设置
   */
  const loadSettings = useCallback(() => {
    try {
      const stored = localStorage.getItem(STORAGE_KEY)
      if (stored) {
        const parsedSettings = JSON.parse(stored) as BarrageSettings
        // 验证设置的完整性，缺失的字段使用默认值
        const validatedSettings: BarrageSettings = {
          ...DEFAULT_BARRAGE_SETTINGS,
          ...parsedSettings
        }
        setSettings(validatedSettings)
        return validatedSettings
      }
    } catch (error) {
      console.warn('加载弹幕设置失败，使用默认设置:', error)
    }
    return DEFAULT_BARRAGE_SETTINGS
  }, [])

  /**
   * 保存设置到本地存储
   */
  const saveSettings = useCallback((settingsToSave: BarrageSettings) => {
    try {
      localStorage.setItem(STORAGE_KEY, JSON.stringify(settingsToSave))
    } catch (error) {
      console.error('保存弹幕设置失败:', error)
    }
  }, [])

  /**
   * 更新单个设置项
   */
  const updateSetting = useCallback(<K extends keyof BarrageSettings>(
    key: K,
    value: BarrageSettings[K]
  ) => {
    setSettings(prevSettings => {
      const newSettings = { ...prevSettings, [key]: value }
      
      // 触发变更事件
      const changeEvent: SettingChangeEvent = {
        key,
        value,
        previousValue: prevSettings[key]
      }
      
      changeListeners.forEach(listener => {
        try {
          listener(changeEvent)
        } catch (error) {
          console.error('设置变更监听器执行失败:', error)
        }
      })
      
      // 自动保存
      saveSettings(newSettings)
      
      return newSettings
    })
  }, [changeListeners, saveSettings])

  /**
   * 批量更新设置
   */
  const updateSettings = useCallback((newSettings: Partial<BarrageSettings>) => {
    setSettings(prevSettings => {
      const updatedSettings = { ...prevSettings, ...newSettings }
      saveSettings(updatedSettings)
      return updatedSettings
    })
  }, [saveSettings])

  /**
   * 重置设置为默认值
   */
  const resetSettings = useCallback(() => {
    setSettings(DEFAULT_BARRAGE_SETTINGS)
    saveSettings(DEFAULT_BARRAGE_SETTINGS)
  }, [saveSettings])

  /**
   * 计算弹出框位置
   */
  const calculatePanelPosition = useCallback(() => {
    if (!settingsButtonRef.current) return { x: 0, y: 0 }
    
    const buttonRect = settingsButtonRef.current.getBoundingClientRect()
    const viewportWidth = window.innerWidth
    const viewportHeight = window.innerHeight
    
    // 弹出框预估尺寸
    const panelWidth = 320
    const panelHeight = 400
    
    let x = buttonRect.right + 10 // 默认在按钮右侧
    let y = buttonRect.top
    
    // 检查右侧是否有足够空间
    if (x + panelWidth > viewportWidth) {
      x = buttonRect.left - panelWidth - 10 // 移到左侧
    }
    
    // 检查垂直位置
    if (y + panelHeight > viewportHeight) {
      y = viewportHeight - panelHeight - 20 // 调整到视口内
    }
    
    // 确保不超出视口边界
    x = Math.max(10, Math.min(x, viewportWidth - panelWidth - 10))
    y = Math.max(10, Math.min(y, viewportHeight - panelHeight - 10))
    
    return { x, y }
  }, [])

  /**
   * 打开设置面板
   */
  const openPanel = useCallback(() => {
    const position = calculatePanelPosition()
    setPanelState({
      isOpen: true,
      position,
      animating: true
    })
    
    // 动画完成后设置 animating 为 false
    setTimeout(() => {
      setPanelState(prev => ({ ...prev, animating: false }))
    }, 300)
  }, [calculatePanelPosition])

  /**
   * 关闭设置面板
   */
  const closePanel = useCallback(() => {
    setPanelState(prev => ({ ...prev, animating: true }))
    
    // 动画完成后关闭面板
    setTimeout(() => {
      setPanelState(DEFAULT_PANEL_STATE)
    }, 300)
  }, [])

  /**
   * 切换设置面板显示状态
   */
  const togglePanel = useCallback(() => {
    if (panelState.isOpen) {
      closePanel()
    } else {
      openPanel()
    }
  }, [panelState.isOpen, openPanel, closePanel])

  /**
   * 添加设置变更监听器
   */
  const addChangeListener = useCallback((listener: (event: SettingChangeEvent) => void) => {
    setChangeListeners(prev => [...prev, listener])
    
    // 返回移除监听器的函数
    return () => {
      setChangeListeners(prev => prev.filter(l => l !== listener))
    }
  }, [])

  /**
   * 获取设置的显示标签
   */
  const getSettingLabel = useCallback((key: keyof BarrageSettings): string => {
    const labels: Record<keyof BarrageSettings, string> = {
      fontSize: '字体大小',
      opacity: '透明度',
      speed: '移动速度',
      avoidPerson: '人物防遮盖',
      displayArea: '显示区域',
      barrageEnabled: '弹幕开关',
      density: '弹幕密度',
      mode: '弹幕模式',
      screenScale: '屏幕缩放',
      preventBlock: '防遮挡'
    }
    return labels[key] || key
  }, [])

  /**
   * 验证设置值是否有效
   */
  const validateSetting = useCallback(<K extends keyof BarrageSettings>(
    key: K,
    value: BarrageSettings[K]
  ): boolean => {
    switch (key) {
      case 'fontSize':
        return [12, 18, 24, 30].includes(value as number)
      case 'opacity':
        return [25, 50, 75, 100].includes(value as number)
      case 'speed':
        return [120, 150, 180, 230].includes(value as number)
      case 'avoidPerson':
        return typeof value === 'boolean'
      case 'displayArea':
        return ['quarter', 'half', 'threequarter', 'fullscreen'].includes(value as string)
      case 'barrageEnabled':
        return typeof value === 'boolean'
      default:
        return true
    }
  }, [])

  // 组件挂载时加载设置
  useEffect(() => {
    loadSettings()
  }, [loadSettings])

  // 监听窗口大小变化，重新计算弹出框位置
  useEffect(() => {
    if (!panelState.isOpen) return
    
    const handleResize = () => {
      const position = calculatePanelPosition()
      setPanelState(prev => ({ ...prev, position }))
    }
    
    window.addEventListener('resize', handleResize)
    return () => window.removeEventListener('resize', handleResize)
  }, [panelState.isOpen, calculatePanelPosition])

  // 监听点击外部关闭面板
  useEffect(() => {
    if (!panelState.isOpen) return
    
    const handleClickOutside = (event: MouseEvent) => {
      const target = event.target as Node
      
      // 检查点击是否在面板或设置按钮内
      if (
        panelRef.current && !panelRef.current.contains(target) &&
        settingsButtonRef.current && !settingsButtonRef.current.contains(target)
      ) {
        closePanel()
      }
    }
    
    // 延迟添加监听器，避免立即触发
    const timer = setTimeout(() => {
      document.addEventListener('mousedown', handleClickOutside)
    }, 100)
    
    return () => {
      clearTimeout(timer)
      document.removeEventListener('mousedown', handleClickOutside)
    }
  }, [panelState.isOpen, closePanel])

  // 监听 ESC 键关闭面板
  useEffect(() => {
    if (!panelState.isOpen) return
    
    const handleKeyDown = (event: KeyboardEvent) => {
      if (event.key === 'Escape') {
        closePanel()
      }
    }
    
    document.addEventListener('keydown', handleKeyDown)
    return () => document.removeEventListener('keydown', handleKeyDown)
  }, [panelState.isOpen, closePanel])

  return {
    // 状态
    settings,
    panelState,
    
    // 引用
    settingsButtonRef,
    panelRef,
    
    // 设置操作
    updateSetting,
    updateSettings,
    resetSettings,
    loadSettings,
    saveSettings,
    
    // 面板操作
    openPanel,
    closePanel,
    togglePanel,
    
    // 工具函数
    addChangeListener,
    getSettingLabel,
    validateSetting
  }
}

export default useBarrageSettings
